定义
一个类中应该是一组相关性很高的函数、数据的封装,下面以一个例子为例来说,本文均来自《Android源码设计模式解析与实战》。
举例
下面是一个简单的图片加载器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| public class ImageLoader { LruCache<String, Bitmap> mImageCache; ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); public ImageLoader() { initImageCache(); } private void initImageCache() { final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); final int cacheSize = maxMemory / 4; mImageCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String ker, Bitmap bitmap) { return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } }; } public void displayImage(final String url, final ImageView imageView) { imageView.setTag(url); mExecutorService.submit(new Runnable() { @Override public void run() { Bitmap bitmap = downloadImage(url); if (bitmap == null) { return; } if (imageView.getTag().equals(url)) { imageView.setImageBitmap(bitmap); } mImageCache.put(url, bitmap); } }); } public Bitmap downloadImage(String imageUrl) { Bitmap bitmap = null; try { URL url = new URL(imageUrl); final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); bitmap = BitmapFactory.decodeStream(conn.getInputStream()); conn.disconnect(); } catch (Exception e) { e.printStackTrace(); } return bitmap; } }
|
上面这段代码乍一看好像并没有什么问题,该实现的功能都实现了,但真的是这样吗?我的类名是ImageLoader,但是很明显的发现其中夹杂了ImageCache的代码,现在我们将上面代码进行修改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class ImageLoader { ImageCache mImageCache = new ImageCache(); ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); public void displayImage(final String url, final ImageView imageView) { Bitmap bitmap = mImageCache.get(url); if (bitmap != null) { imageView.setImageBitmap(bitmap); return; } imageView.setTag(url); mExecutorService.submit(new Runnable() { @Override public void run() { Bitmap bitmap = downloadImage(url); if (bitmap == null) { return; } if (imageView.getTag().equals(url)) { imageView.setImageBitmap(bitmap); } mImageCache.put(url, bitmap); } }); } public Bitmap downloadImage(String imageUrl) { Bitmap bitmap = null; try { URL url = new URL(imageUrl); final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); bitmap = BitmapFactory.decodeStream(conn.getInputStream()); conn.disconnect(); } catch (Exception e) { e.printStackTrace(); } return bitmap; } }
|
使用ImageCache类用于处理图片缓存:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class ImageCache { LruCache<String, Bitmap> mImageCache; public ImageCache() { initImageCache(); } private void initImageCache() { final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); final int cacheSize = maxMemory / 4; mImageCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String ker, Bitmap bitmap) { return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } }; } public void put(String url, Bitmap bitmap) { mImageCache.put(url, bitmap); } public Bitmap get(String url) { return mImageCache.get(url); } }
|
这样修改之后,ImageLoader只负责图片加载的逻辑,而ImageCache只负责处理图片缓存的逻辑。这样ImageLoader的代码量变少了,职责也清晰了,当与缓存相关的逻辑需要改变时,不需要修改ImageLoader类,而图片加载的相关逻辑需要修改时也不会影响到缓存逻辑处理。
的确,这样修改了之后,确实职责都划分开了,但是可扩展性还是比较欠缺,上面的ImageCache是缓存在内存中的,如果还有缓存在本地的需求又该如何呢?
总结
单一职责原则有一些基本的指导原则,比如:
- 两个完全不一样的功能就不应该放在同一个类中,这样会导致类变得臃肿复杂
- 一个类中应该是一组相关性很高的函数、数据的封装